/*
 * Classe ListOne
 *                          - Obtem os dados da lista 1 da base de dados (SQLite3 + ADO.NET) 
 * 							- Guarda esses dados numa Lista (C# Collections)
 * 							- Ordena os dados
 * 							- Escreve os resultados na consola e no ficheiro de texto respectivo
 *							- Tem como atributo o estabelecimento sobre o qual serão obtidos os dados
 *
 *@Author: Fábio Miguel Vitória Carreto - 5618 - Engenharia Informática - Diurno
 *@Version: 03/07/2011
 * 
 * 
 * */

using System;
using System.Collections.Generic;
using System.Data;
using Mono.Data.SqliteClient;
using System.IO;

public class ListOne
{
	public string estabelecimento;
	
	public ListOne (string estabelecimento)
	{
		this.estabelecimento =  estabelecimento;
		
		//Para cada ano executa os seguintes métodos
		for(int ano = 0 ; ano < 10 ; ano++)
		{
			//Obtém a lista 1 mas apenas com os ids dos docentes
			List<IdDocente> listIds = this.getData(ano);
			//Através dos ids obtem a lista definitiva com os nomes dos docentes respectivos
			List<StructListOne> listOne = this.getDataFinal(ano, listIds);
			//Ordena a lista obtida
			List<StructListOne> listOrdenada = this.mostraListaOrdenada(listOne);
			//Mostra os resultados na consola
			this.showResultsConsole(listOrdenada, ano);
			//Mostra os resultados num ficheiro de texto
			this.showResultsFile(listOrdenada, ano);	
		}

	}
	
	//Ordena os dados por ordem alfabética do nome de docente
	public List<StructListOne> mostraListaOrdenada(List<StructListOne> list)
	{
		list.Sort(delegate(StructListOne s1, StructListOne s2) { return s1.docente.CompareTo(s2.docente); });
		
		return list;
	}
	
	//Mostra resultados na consola
	public void showResultsConsole(List<StructListOne> list, int ano)
	{
		
		Console.WriteLine("ANO DE 200" + ano + "\nDOCENTES:");
		Console.WriteLine("\nResultados (Ordenados por Ordem Alfabética em Cada Ano):\n");
		list.ForEach(delegate(StructListOne s) 
		{ 
			Console.WriteLine(s.docente); 
		});
		
	}
	
	//Mostra resultados no ficheiro respectivo
	public void showResultsFile(List<StructListOne> list, int ano)
	{
		string file = "Listas/listOne.txt";
		
		//Quando o ano é 0, é definido o cabeçalho da lista
		if(ano == 0)
		{
			
			TextWriter tw = new StreamWriter(file);
			tw.WriteLine(DateTime.Now);
			tw.WriteLine("Sistema Operativo: " + Environment.OSVersion.ToString());
			tw.WriteLine("");
			tw.WriteLine("Lista 1 - Docentes doutorados ou com grau equivalente (3º ciclo) " +
				"no estabelecimento " + this.estabelecimento);
			tw.WriteLine(Environment.NewLine + "(Resultados ordenados por ordem alfabética em cada ano)");
			tw.WriteLine("Estabelecimento: " + this.estabelecimento);
			tw.Close();
			
		}
		//Depois define-se consoante o resultado que vem na lista recebida
		File.AppendAllText(file, "Grau: Doutorados ou com grau equivalente (3º ciclo)" + Environment.NewLine);
		
		list.ForEach(delegate(StructListOne s) 
		{
			File.AppendAllText(file, String.Format("Ano = 200{0}, Docente = {1}" + 
			                                       Environment.NewLine, s.year, s.docente));
		});
		
		File.AppendAllText(file, Environment.NewLine + Environment.NewLine);
		
		Console.WriteLine("\nOs resultados da lista 1 foram também guardados em ficheiro de texto.");
		Console.WriteLine("Localização: " + file);
		
	}
	
	//Obtém os dados da lista e retorna-os numa lista de 
	//objectos que contém apenas os ids dos docentes pretendidos
	public List<IdDocente> getData(int ano)
	{
		
		string connectionString = "URI=file:rebides.db,version=3";
		IDbConnection dbcon;
		dbcon = (IDbConnection) new SqliteConnection(connectionString);
		dbcon.Open();
		IDbCommand dbcmd = dbcon.CreateCommand();
		
		List<IdDocente> list = new List<IdDocente>();
		
		IDataReader reader = null;
		
		//Verifica qual o codigo do estabelecimento no ano em questão
		string sqlEstab = String.Format("SELECT DISTINCT id FROM estabelecimento WHERE " +
				"ano = {0} AND designacao LIKE '{1}'", ano, this.estabelecimento);
			 
		dbcmd.CommandText = sqlEstab;
		reader = dbcmd.ExecuteReader();
		
		string estabelecimento_id = null;
		
		while(reader.Read()) 
		{
			estabelecimento_id = reader.GetString (0);
		}
		
		//Obtem todos os ids de docente cujo ciclo de estudos é terceiro (ou seja, doutoramento ou equivalente)
		//e cujo estabelecimento e anos são os pretendidos
		string sqlFinal = String.Format("SELECT DISTINCT docente_id " +
			"FROM registodocencia, grau, cicloestudo " +
			"WHERE ano = {0} " +
			"AND estabelecimento_id = {1} " +
			"AND grau_id = grau.id " +
			"AND grau.ciclo_estudos_id = cicloestudo.id " +
			"AND cicloestudo.designacao LIKE 'terceiro'", ano, estabelecimento_id);
	
		dbcmd.CommandText = sqlFinal;
		reader = dbcmd.ExecuteReader();
		
		while(reader.Read()) 
		{
			string docente = reader.GetString (0);
			//Adiciona cada resultado à lista de objectos de ids dos docentes 
			list.Add(new IdDocente(int.Parse(docente)));
		}

		return list;
		
	}
	
	//Recebe como parâmetro a lista com os ids de docentes
	//cujo ciclo de estudos é terceiro (ou seja, doutoramento ou equivalente)
	//e cujo estabelecimento e anos são os pretendidos
	//Devolve depois a mesma lista mas já com os nomes de docentes respeitantes a cada ID
	public List<StructListOne> getDataFinal(int ano, List<IdDocente> listIds)
	{
		
		string connectionString = "URI=file:rebides.db,version=3";
		IDbConnection dbcon;
		dbcon = (IDbConnection) new SqliteConnection(connectionString);
		dbcon.Open();
		IDbCommand dbcmd = dbcon.CreateCommand();
		
		List<StructListOne> list = new List<StructListOne>();
		IDataReader reader = null;
		
		foreach(IdDocente id_docente in listIds)
		{
			string sqlFinal = String.Format("SELECT DISTINCT nome FROM docente " + 
			                                "WHERE id = {0} ", id_docente.id);
			dbcmd.CommandText = sqlFinal;
			reader = dbcmd.ExecuteReader();
			
			while(reader.Read()) 
			{
				string docente = reader.GetString (0);
				
				//Adiciona os resultados dos nomes à lista de objectos
				//que será a final(embora ainda desordenada)
				list.Add(new StructListOne(ano, docente, this.estabelecimento, "Doutoramento (e equivalentes)"));
			}
				
		
		}
		
		return list;
		
	}
}

//Objecto que servirá de base à lista final
//Tem como atributos o ano, o docente, o estabelecimento 
// e o grau que será sempre o mesmo (doutoramento e equivalentes)
public class StructListOne
{
	public int year;
	public string docente;
	public string estabelecimento;
	public string grau;
	
	public StructListOne(int year, string docente, string estabelecimento, string grau)
	{
		this.year = year;
		this.docente = docente;
		this.estabelecimento = estabelecimento;
		this.grau = grau;
	}
}
//Objecto que servirá controlo à lista
//Tem como atributos o id de docente e
//servirá para obter a lista inicial
public class IdDocente
{
	public int id;
	
	public IdDocente(int id)
	{
		this.id = id;
		
	}
}